package com.hd.manager.task;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hd.appcommon.entity.Course;
import com.hd.appcommon.entity.CourseScore;
import com.hd.appcommon.entity.User;
import com.hd.appcommon.service.CourseScoreService;
import com.hd.appcommon.service.CourseService;
import com.hd.appcommon.service.UserService;
import com.hd.appcommon.utils.HzieeAPIUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Component
public class CourseScoreSync {

    @Autowired
    CourseService courseService;
    @Autowired
    CourseScoreService courseScoreService;
    @Autowired
    UserService userService;
    @Autowired
    HzieeAPIUtils hzieeAPIUtils;
    @Autowired
    ExecutorUtil executorUtil;

    //同步所有学生的信息
    public void courseScoreSync(String year, String term) {
        QueryWrapper wrapper = new QueryWrapper<>()
                .select("job_number")
                .eq("type",1);
        List<User> userList= userService.list(wrapper);
        List<String> snoList = userList.stream().map(User::getJobNumber).collect(Collectors.toList());

        log.info("开始更新全体学生的课程成绩，总数{}",snoList.size());

        for (int i = 0; i < snoList.size(); i++) {
            String sno = snoList.get(i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                log.error("do something error: ", e);
            }
            try {
                log.info("开始更新第{}个学生 {} 的课程成绩数据", i, sno);
                executorUtil.courseScoreSync_Stu_async(sno, null, null);
                log.info("结束更新第{}个学生 {} 的课程成绩数据", i, sno);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        courseCreditSync( null, year, term);
    }



    //将某个学生的成绩更新到数据库
    public void courseScoreSync_Stu(String sno, String year, String term) {

        List<CourseScore> courseScoreList = getCourseScore(sno, year, term);
        if (courseScoreList==null || courseScoreList.size()==0){
            return;
        }
        courseScoreList = courseScoreList.stream().distinct().collect(Collectors.toList());

        QueryWrapper wrapper = new QueryWrapper<>()
                .eq("sno", sno)
                .eq(year!=null,"year", year)
                .eq(term!=null,"term", term);
        List<CourseScore> courseScoreListDB = courseScoreService.list(wrapper);
        List<CourseScore> saveList = new ArrayList<>();
        List<CourseScore> updateList = new ArrayList<>();


        for (int i = 0; i < courseScoreList.size(); i++) {
            CourseScore item = courseScoreList.get(i);
            Boolean save = true;
            for (int j = 0; j < courseScoreListDB.size(); j++) {
                CourseScore itemDB = courseScoreListDB.get(j);
                if (item.getSno().equals(itemDB.getSno()) &&
                        item.getCourCode().equals(itemDB.getCourCode()) &&
                        item.getCourName().equals(itemDB.getCourName())) {
                    item.setId(itemDB.getId());
                    updateList.add(item);
                    save = false;
                    break;
                }
            }
            if (save) {
                saveList.add(item);
            }
        }

        if (saveList.size() > 0) {
            courseScoreService.saveBatch(saveList);
        }
        if (updateList.size() > 0) {
            courseScoreService.updateBatchById(updateList);
        }
    }

    //获取某一个学生的成绩，转换为CourseScore对象
    public List<CourseScore> getCourseScore(String sno, String year, String term) {
        JSONObject res = hzieeAPIUtils.requestCourseScores(sno, year, term, 1, 200);
        System.out.println(res);
        if (Integer.valueOf(res.getString("total")) > 200) {
            log.error("获取的信息条数超过page的size！");
            return null;
        }
        JSONArray records = res.getJSONArray("records");

        List<CourseScore> courseScoreList = new ArrayList<>();
        for (int i = 0; i < records.size(); i++) {
            JSONObject recode = records.getJSONObject(i);
            CourseScore courseScore = new CourseScore();
            courseScore.setSno(recode.getString("XH"));
            courseScore.setName(recode.getString("XM"));
            courseScore.setYear(recode.getString("XN"));
            courseScore.setTerm(recode.getString("XQM"));
            courseScore.setCourCode(recode.getString("KCH"));
            courseScore.setCourName(recode.getString("KCMC"));
            courseScore.setClassCode(recode.getString("KCXKH"));
            courseScore.setCourScore(recode.getString("QMCJ").equals("") ? recode.getString("SYCJ") : recode.getString("QMCJ"));
            if (!recode.getString("CJJD").equals("")) {
                courseScore.setCourGpa(recode.getFloat("CJJD"));
            }
            courseScore.setCourCredit(Float.valueOf(0));
            courseScoreList.add(courseScore);
        }

        return courseScoreList;
    }

    //根据排课表中的信息,更新学生成绩表中的学分字段
    public void courseCreditSync(String sno,String year,String term){
        log.info("being-根据排课表中的信息,更新学生成绩表中的学分字段.sno={},year={},term={}",sno,year,term);
        QueryWrapper wrapper = new QueryWrapper<>()
                .select("cour_code","cour_credit");
        List<Course> courseList = courseService.list(wrapper);

        log.info("获取课程条数："+courseList.size());
        courseList = courseList.stream().distinct().collect(Collectors.toList());
        log.info("获取课程条数（去重后）："+courseList.size());


        Integer updateNum = courseScoreService.courseCreditSync(sno,year,term);
        log.info("end-更新成功条数："+updateNum);
    }



    //多线程辅助内部类
    @Component
    class ExecutorUtil {
        @Async("asyncServiceExecutor")
        public void courseScoreSync_Stu_async(String sno, String year, String term) {
            try{
                courseScoreSync_Stu(sno, year, term);
            }catch (Exception e){
                e.printStackTrace();
            }

        }

    }

}
